<?php


namespace PKFrame\DataHandler;
defined('PATH_PK') or die();


class MatchHelper
{

    // 正则列表
    private const list = array(
        'num' => '/^[0-9.-]+$/',
        'int' => '/^[0-9-]+$/',
        'letter' => '/^[a-z]+$/i',
        'letterNum' => '/^[0-9a-z]+$/i',
        'letter_num' => '/^[0-9a-z_]+$/i',
        'letter_' => '/^[a-z_]+$/i',
        'file_name' => '/^[0-9a-z.]+$/i',
        'email' => '/^[\w\-\.]+@[\w\-\.]+(\.\w+)+$/',
        'qq' => '/^[0-9]{5,20}$/',
        'url' => '/^http:\/\//',
        'mobile' => '/^(1)[0-9]{10}$/',
        'tel' => '/^[0-9-]{6,13}$/',
        'zipCode' => '/^[0-9]{6}$/',
        'date' => '/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/',
        'dateTime' => '/^\d{4}[\-](0?[1-9]|1[012])[\-](0?[1-9]|[12][0-9]|3[01])(\s+(0?[0-9]|1[0-9]|2[0-3])\:(0?[0-9]|[1-5][0-9])\:(0?[0-9]|[1-5][0-9]))?$/',
        'ip' => '/^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1 -9]?\d))))$/',
        // 以下两种都可以
//        'color' => '/^#([a-fA-F\d]{6}|[a-fA-F\d]{3})$/',
        'color' => '/^#([A-F\d]{6}|[A-F\d]{3})$/i',
        'password' => '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\s\S]{8,16}$/'
    );

    /**
     * 匹配格式
     * @param string $type
     * @param string $data
     * @param string $tips
     * @param string|null $app
     * @param array|null $replace_params
     */
    public static function MatchFormat(string $type = '', $data = '', string $tips = '',
                                       string $app = null, array $replace_params = null)
    {
        try {
            if (empty($data) || is_array($data)) {
                throw new \Exception(language('MatchFormat_DataEmpty'));
            }
            if (!array_key_exists($type, self::list)) {
                throw new \Exception(language('MatchFormat_TypeNoExists' . $type));
            }
            if (!preg_match(self::list[$type], $data)) {
                $tips = language($tips, $app);
                if (!is_null($replace_params)) {
                    list($search_list, $replace_list) = $replace_params;
                    $tips = str_replace($search_list, $replace_list, $tips);
                }
                throw new \Exception($tips);
            }
        } catch (\Exception $e) {
            request()->isAjax() ? out()->noticeByJson($e->getMessage()) : out()->notice($e->getMessage());
        }
    }

    public static function MatchFormatOfBool(string $type = '', $data = ''): bool
    {
        if (empty($data) || is_array($data)) {
            return false;
        }
        if (!array_key_exists($type, self::list)) {
            return false;
        }
        return boolval(preg_match(self::list[$type], $data));
    }

    public static function checkCheckBox(string $str)
    {
        return preg_match('/^[0-9,]+$/', $str);
    }

    /**
     * 检查（下载）URL合法性
     * @param $url
     * @return false|int
     */
    public static function checkUrlOfDownLoad($url)
    {
        return preg_match("/^(http|https|ftp)(:\/\/)([a-zA-Z0-9-_]+[\.\/]+[\w\-_\/]+.*)+$/i", $url);
    }

    /**
     * 检查 URL 中的 Host 合法性
     * @param string $domain
     * @return bool
     */
    public static function checkUrlOfHost(string $domain): bool
    {
        if (preg_match("/^([0-9a-z-]{1,}.)?[0-9a-z-]{2,}.([0-9a-z-]{2,}.)?[a-z]{2,}$/i", $domain)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 检查 URL 是否带有协议
     * @param string $url
     * @return bool
     */
    public static function checkUrlOfScheme(string $url): bool
    {
        $urls = parse_url($url);
        if (Arrays::Is($urls) >= 2 && array_key_exists('scheme', $urls) && array_key_exists('host', $urls)) {
            $checkScheme_isH = in_array($urls['scheme'], ['http', 'https']);
            if ($checkScheme_isH) {
                return self::checkUrlOfHost($urls['host']);
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 在 HTML 代码中获取 P 标签
     * @param string $text
     * @param array|null $output
     * @param bool $isDeCode
     * @return void
     */
    public static function GetPTagInHTMLCode(string $text, array &$output = null, bool $isDeCode = true)
    {
        $text = Pages::Zip(trim($text));
        try {
            if (empty($text)) {
                throw new \Exception('Failed to get P tag, the matched text is empty!');
            } elseif ($isDeCode) {
                $text = Auth::HtmlspecialcharsDeCode($text);
            }
            preg_match_all('/<p.*?>(.*?)<\/p>/', $text, $output);
            if (Arrays::Is($output) >= 2) {
                $output = $output[1];
            }
        } catch (\Exception $exception) {
            handlerException($exception);
        }
    }

    /**
     * 过滤特殊字符
     * @param string $str
     * @return array|string|string[]|null
     */
    public static function FilterSpecialStr(string $str)
    {
        return preg_replace("/[ '.,:;*?~`!@#$%^&+=)(<>{}]|\]|\[|\/|\\\|\"|\|/", "", $str);
    }

    public static function FilterSpecialGraphicStr(string $str)
    {
        return preg_replace("/&(.*?);/si", "", $str);
    }

    /**
     * 判断在字符串中是否存在中文
     * @param string $str
     * @return bool
     */
    public static function isInStrExistsCn(string $str): bool
    {
        $pattern = "/[^\x{4E00}-\x{9FFF}]+/u";
        $newStr = preg_replace($pattern, '', $str);
        return empty($newStr);
    }

    public static function filterListWordOfStr(string $str, array $list_word)
    {
        $list_filterWord = '/' . implode('|', $list_word) . '/';
        preg_match_all($list_filterWord, $str, $matches);
        return end($matches);
    }
}